package com.zhouhx.flow.tasklist;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.Setting;
import com.alibaba.fastjson2.JSON;
import com.zhouhx.flow.tasklist.entity.FlowInstance;
import com.zhouhx.flow.tasklist.entity.FlowStep;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author : zhouhx
 * @date : 2024/3/30 11:18
 */
@Slf4j
@Component
public class TaskLog {
    private static final String logPath= "/logs";
    /**
     * 流程步骤日志
     */
    private static final String STEP_TASK_LOG="stepTaskLog-%s.setting";
    /**
     * 流程实例日志
     */
    private static final String FLOW_TASK_LOG="flowTaskLog-%s.setting";
    /**
     * 日志文件最大大小 100M
     */
    private static final Long MAX_LOG_SIZE= 104857600L;
    @PostConstruct
    public void createLog(){
        createFile(getTaskLogName(STEP_TASK_LOG),"流程步骤日志");
        createFile(getTaskLogName(FLOW_TASK_LOG),"流程实例日志");
    }

    /**
     * 获取日志文件名
     * @return 日志文件名
     */
    public static String getTaskLogName(String logName){
        return String.format(logName, DateUtil.formatDate(new Date()));
    }
    
    /**
     * 创建日志文件
     * @param logFileName 日志文件名
     * @param logName 日志名称
     */
    private static void createFile(String logFileName, String logName) {
        File autoTaskLogFile = new File(String.format("%s/%s", logPath, logFileName));
        if(!autoTaskLogFile.exists()){
            try {
                // 如果父目录不存在，则需要先创建父目录
                if (!autoTaskLogFile.getParentFile().exists()) {
                    autoTaskLogFile.getParentFile().mkdirs();
                }
                autoTaskLogFile.createNewFile();
            }catch (Exception e){
                log.error(String.format("创建%s文件失败",logName),e);
            }
        }
    }

    /**
     * 生成流程步骤日志
     * @param flowName 流程名称
     * @param flowInstanceId 序列号
     * @param content 日志内容
     */
    public synchronized static void generateStepLog(String flowName,String flowInstanceId, FlowStep content){
        if(StrUtil.isBlank(flowName) || StrUtil.isBlank(flowInstanceId)){
            return;
        }
        // 打开文件
        try {
            generateLog(getTaskLogName(STEP_TASK_LOG), flowName, flowInstanceId, content,FlowStep.class);
        } catch (Exception e) {
            log.error(">>>>>>生成流程步骤日志失败",e);
        }
    }

    /**
     * 生成流程实例日志
     * @param flowId 流程id
     * @param flowInstanceId 序列号
     * @param flowInstance 日志内容
     */
    public synchronized static void generateFlowLog(String flowId,String flowInstanceId, FlowInstance flowInstance){
        if(StrUtil.isBlank(flowId) || StrUtil.isBlank(flowInstanceId)){
            return;
        }
        // 打开文件
        try {
            generateLog(getTaskLogName(FLOW_TASK_LOG), flowId, flowInstanceId, flowInstance,FlowInstance.class);
        } catch (Exception e) {
            log.error(">>>>>>生成流程实例日志失败",e);
        }
    }
    /**
     * 生成日志
     * @param logFileName 日志文件名
     * @param flowName 流程名称
     * @param flowInstanceId 序列号
     * @param content 日志内容
     * @param contentType 类类型
     */
    private  static <T> void generateLog(String logFileName, String flowName, String flowInstanceId, T content, Class<T> contentType) {
        Setting setting = new Setting(String.format("file:%s/%s", logPath, logFileName));
        if(setting.containsKey(flowName, flowInstanceId)){
            String jsonStr = setting.getStr(flowInstanceId, flowName,null);
            if(StrUtil.isNotBlank(jsonStr)){
                List<T> contents = JSON.parseArray(jsonStr, contentType);
                contents.add(content);
                setting.setByGroup(flowInstanceId,flowName,JSON.toJSONString(contents));

                setting.store(String.format("file:%s/%s", logPath, logFileName));
            }
        }else{
            // 新入库得流程看文件大小是否超限制
            File file = new File(String.format("%s/%s", logPath, logFileName));
            if(file.length() > MAX_LOG_SIZE){
                // 创建新文件
                logFileName = String.format("%s.%s", logFileName, System.currentTimeMillis());
                createFile(logFileName, logFileName);
                setting = new Setting(String.format("%s/%s", logPath, logFileName));
            }
            List<T> contents = new ArrayList<>();
            contents.add(content);
            setting.setByGroup(flowInstanceId,flowName,JSON.toJSONString(contents));

            setting.store(String.format("file:%s/%s", logPath, logFileName));
        }
    }
}
